/**
 * 
 */
package cvcg.model;

import java.io.Serializable;
import java.util.HashSet;
import java.util.Set;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.JoinTable;
import javax.persistence.ManyToMany;
import javax.persistence.Table;
import javax.persistence.Transient;

import org.hibernate.annotations.ForeignKey;
import org.hibernate.annotations.Type;

/**
 * @author jaracje
 * 
 */
@Entity
@Table(name="PLAYER")
@SuppressWarnings("serial")
public class Player implements Serializable 
{		
	@Id
	@GeneratedValue
	@Column(name="PLAYER_P")
	private Long id;
	@Column(unique=true)
	private String name;
	private String email;
	private String password;
	@Type(type="yes_no")
	@Column(nullable=false ,columnDefinition="char(1) default 'Y'")
	private Boolean multiTable = Boolean.TRUE;
	
	@ManyToMany(targetEntity=Game.class,fetch=FetchType.EAGER)
	@JoinTable(name = "OWNEDGAME", joinColumns =
	{ @JoinColumn(name = "PLAYER_F") }, inverseJoinColumns =
	{ @JoinColumn(name = "GAME_F") })
	@ForeignKey(name = "CTR_OWNG_R_PLAYER", inverseName = "CTR_OWNG_R_GAME")
	private Set<Game> ownedGames = new HashSet<Game>();
	
	@ManyToMany(targetEntity=Game.class,fetch=FetchType.EAGER)
	@JoinTable(name = "RULEMASTEREDGAME", joinColumns =
	{ @JoinColumn(name = "PLAYER_F") }, inverseJoinColumns =
	{ @JoinColumn(name = "GAME_F") })
	@ForeignKey(name = "CTR_RMG_R_PLAYER", inverseName = "CTR_RMG_R_GAME")
	private Set<Game> ruleMasteredGames = new HashSet<Game>();
	
	@ManyToMany(fetch=FetchType.EAGER)
	@JoinTable(name = "USERROLE", joinColumns =
	{ @JoinColumn(name = "PLAYER_F") }, inverseJoinColumns =
	{ @JoinColumn(name = "ROLE_F") })
	@ForeignKey(name = "CTR_USERROLES_R_PLAYER", inverseName = "CTR_USERROLES_R_ROLE")	
	private Set<Role> roles = new HashSet<Role>();
	
	public Long getId() {
		return id;
	}

	public void setId(Long id) {
		this.id = id;
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public Set<Game> getOwnedGames() {
		return ownedGames;
	}

	public void setOwnedGames(Set<Game> ownedGames) {
		this.ownedGames = ownedGames;
	}

	public Set<Game> getRuleMasteredGames() {
		return ruleMasteredGames;
	}

	public void setRuleMasteredGames(Set<Game> ruleMasteredGames) {
		this.ruleMasteredGames = ruleMasteredGames;
	}

	public String getEmail() {
		return email;
	}

	public void setEmail(String email) {
		this.email = email;
	}

	public String getPassword() {
		return password;
	}

	public void setPassword(String password) {
		this.password = password;
	}
	
	public Set<Role> getRoles() {
		return roles;
	}

	public void setRoles(Set<Role> roles) {
		this.roles = roles;
	}
			
	public Boolean getMultiTable() {
		return multiTable;
	}

	public void setMultiTable(Boolean multiTable) {
		this.multiTable = multiTable;
	}

	/**
	 * @param game
	 */
	@Transient
	public void addOwnedGame(Game game) 
	{
		ownedGames.add(game);
	}
	
	/**
	 * @param game
	 */
	@Transient
	public void addRuleMasteredGame(Game game) 
	{
		ruleMasteredGames.add(game);
	}
	
	/**
	 * @param role
	 */
	@Transient 
	public void addRole(Role role) 
	{
		roles.add(role);
	}
	/**
	 * Obtain set of owned games for current player 
	 * matching the game session's attending player count
	 * (example, for 4 players attending a game session :
	 * will add all owned games having maxPlayer <= 4  and minPlayer >= 4)  
	 * @param attendingPlayerCount game session's attending player count
	 * @return set of owned game 
	 */
	@Transient
	public Set<Game> getOwnedGamesForGameSession(Integer attendingPlayerCount) 
	{
		Set<Game> games = new HashSet<Game>();
		if (ownedGames!=null) 
		{
			for (Game game : ownedGames) 
			{		
				if (game.getMaxPlayer()!=null 
				    && game.getMinPlayer()!=null 
				    && attendingPlayerCount.compareTo(game.getMaxPlayer()) <= 0  
				    && attendingPlayerCount.compareTo(game.getMinPlayer()) >= 0) 
				{
					games.add(game);
				}
			}
		}
		return games;
	}
	
	@Transient
	public boolean isGameOwned(Game game) 
	{		
		if (ownedGames!=null) 
		{
			return ownedGames.contains(game);
		}
		return false;
	}
	
	/**
	 * Obtain set of rule mastered games for current player 
	 * matching the game session's attending player count
	 * (example, for 4 players attending a game session :
	 * will add all owned games having maxPlayer <= 4  and minPlayer >= 4)  
	 * @param attendingPlayerCount game session's attending player count
	 * @return set of owned game 
	 */
	@Transient
	public Set<Game> getRuleMasteredGamesForGameSession(Integer attendingPlayerCount) 
	{
		Set<Game> games = new HashSet<Game>();
		if (ruleMasteredGames!=null) 
		{
			for (Game game : ruleMasteredGames) 
			{		
				if (game.getMaxPlayer()!=null 
				    && game.getMinPlayer()!=null 
				    && attendingPlayerCount.compareTo(game.getMaxPlayer()) <= 0  
				    && attendingPlayerCount.compareTo(game.getMinPlayer()) >= 0) 
				{
					games.add(game);
				}
			}
		}
		return games;
	}

}
